package aiguoclient

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/astaxie/beego/validation"
	"github.com/xxjwxc/public/errors"
	"io/ioutil"
	"log"
	"net/http"
)

type AddOrderOptions struct {
	RecoveryCategoryCode string `json:"recovery_category_code"  valid:"Required"` //货物类别，支持的类别请查看货物类别文档
	CargoName            string `json:"cargo_name"  valid:"Required"`             //货品名CONF_CATEGORY_AIGO_CODE
	EstimatedWeight      string `json:"estimated_weight"  valid:"Required"`       //预估重量 单位：kg, 内容是float，格式:小数点后2位
	Source               string `json:"source"  valid:"Required"`                 //前端应用名(微信小程序)
	MeetBeginAt          string `json:"meet_begin_at"  valid:"Required"`          //预约启示时间，格式：2019-06-29 09:00:00
	MeetEndAt            string `json:"meet_end_at"  valid:"Required"`            //预约结束时间，格式：2019-06-29 09:00:00
	RemarkFromBusiness   string `json:"remark_from_business"`                     //订单备注
	SenderName           string `json:"sender_name"  valid:"Required"`            //发货人姓名
	SenderPhone          string `json:"sender_phone"  valid:"Required"`           //发货人电话 纯数字
	SenderProvinceName   string `json:"sender_province_name"  valid:"Required"`   //发货人所在省
	SenderCityName       string `json:"sender_city_name"  valid:"Required"`       //发货人所在市
	SenderCountyName     string `json:"sender_county_name"  valid:"Required"`     //发货人所在区
	SenderStreetName     string `json:"sender_street_name"`                       //发货人所在的街道办事处（镇）
	SenderDetail         string `json:"sender_detail"  valid:"Required"`          //发货人详细地址
	ReceiverName         string `json:"receiver_name"  valid:"Required"`          //收货人姓名
	ReceiverPhone        string `json:"receiver_phone"  valid:"Required"`         //收货人电话 纯数字
	ReceiverProvinceName string `json:"receiver_province_name"  valid:"Required"` //收货人所在省
	ReceiverCityName     string `json:"receiver_city_name"  valid:"Required"`     //收货人所在市
	ReceiverCountyName   string `json:"receiver_county_name"  valid:"Required"`   //收货人所在区
	ReceiverStreetName   string `json:"receiver_street_name"`                     //收货人所在的街道办事处（镇）
	ReceiverDetail       string `json:"receiver_detail"  valid:"Required"`        //收货人详细地址

}

type AddOrderResponse struct {
	InBusinessOrderNumber string `json:"in_business_order_number"`
	Message               string `json:"message"`
}

type FailResponse struct {
	Errors  map[string][]string `json:"errors"`
	Message string              `json:"message"`
}

//下单
func (cli *Client) AddOrder(innerOrderId string, bodyParam AddOrderOptions) (int, AddOrderResponse, error) {

	reqPath := fmt.Sprintf("business/apps/%d/business-orders/%s", cli.AppID, innerOrderId)
	rawURL := cli.BaseURL + reqPath

	// param check
	valid := validation.Validation{}
	b, err := valid.Valid(&bodyParam)
	if err != nil {
		return 0, AddOrderResponse{}, err
	}
	if !b {
		for _, err := range valid.Errors {
			log.Println(err.Key, err.Message)
		}
		return 0, AddOrderResponse{}, errors.New("参数错误")
	}

	//body数据
	paramJSON, _ := json.Marshal(bodyParam)

	//计算签名
	sign := cli.genSign(reqPath, string(paramJSON))

	//-----------
	req, _ := http.NewRequest("POST", rawURL, bytes.NewReader(paramJSON))
	req.Header.Set("Sign", sign)
	req.Header.Set("App-Key", cli.AppKey)
	req.Header.Add("Content-Type", "application/json")
	resp, err := (&http.Client{}).Do(req)
	if err != nil {
		return 0, AddOrderResponse{}, err
	}
	defer resp.Body.Close()

	respByte, _ := ioutil.ReadAll(resp.Body)

	if resp.StatusCode == 200 || resp.StatusCode == 201 {
		var urlResp AddOrderResponse
		json.Unmarshal(respByte, &urlResp)
		return resp.StatusCode, urlResp, nil
	} else {

		var urlResp FailResponse
		json.Unmarshal(respByte, &urlResp)
		errMsg := fmt.Sprintf("%+v", urlResp)
		return resp.StatusCode, AddOrderResponse{}, errors.New("status!=200 " + errMsg)
	}
	//---------------------

}

//-------------------------------------------

type ListTraceItem struct {
	Time string `json:"time"  valid:"Required"` //货物类别，支持的类别请查看货物类别文档
	Desc string `json:"desc"  valid:"Required"` //货品名CONF_CATEGORY_AIGO_CODE
}

type FailListTraceItemResponse struct {
	Message string `json:"message"`
}

//运单轨迹
/*
	expressCompanyCode 快递公司编号
	trackingNumber     要查询的运单号
*/
func (cli *Client) ListTrace(expressCompanyCode string, trackingNumber string) (int, []ListTraceItem, error) {

	reqPath := fmt.Sprintf("business/apps/%d/waybill/routes?express_company_code=%s&tracking_number=%s", cli.AppID, expressCompanyCode, trackingNumber)
	rawURL := cli.BaseURL + reqPath

	//计算签名
	sign := cli.genSign(reqPath, "")

	//-----------
	req, _ := http.NewRequest("GET", rawURL, nil)
	req.Header.Set("Sign", sign)
	req.Header.Set("App-Key", cli.AppKey)
	resp, err := (&http.Client{}).Do(req)
	if err != nil {
		return 0, nil, err
	}
	defer resp.Body.Close()

	respByte, _ := ioutil.ReadAll(resp.Body)

	if resp.StatusCode == 200 {
		var urlResp []ListTraceItem
		json.Unmarshal(respByte, &urlResp)
		return resp.StatusCode, urlResp, nil
	} else {
		var urlResp FailListTraceItemResponse
		json.Unmarshal(respByte, &urlResp)
		errMsg := fmt.Sprintf("%+v", urlResp)
		return resp.StatusCode, nil, errors.New("status!=200 " + errMsg)
	}
}

//-------------------------------------------

type CancelOrderOptions struct {
	CancelledReasonText string `json:"cancelled_reason_text"  valid:"Required"` //取消原因
}

type CancelOrderResponse struct {
	Message string `json:"message"`
}

//取消
func (cli *Client) CancelOrder(innerOrderId string, bodyParam CancelOrderOptions) (int, CancelOrderResponse, error) {

	reqPath := fmt.Sprintf("business/apps/%d/business-orders/%s/business-cancel", cli.AppID, innerOrderId)
	rawURL := cli.BaseURL + reqPath

	// param check
	valid := validation.Validation{}
	b, err := valid.Valid(&bodyParam)
	if err != nil {
		return 0, CancelOrderResponse{}, err
	}
	if !b {
		for _, err := range valid.Errors {
			log.Println(err.Key, err.Message)
		}
		return 0, CancelOrderResponse{}, errors.New("参数错误")
	}

	//body数据
	paramJSON, _ := json.Marshal(bodyParam)

	//计算签名
	sign := cli.genSign(reqPath, string(paramJSON))

	//-----------
	req, _ := http.NewRequest("POST", rawURL, bytes.NewReader(paramJSON))
	req.Header.Set("Sign", sign)
	req.Header.Set("App-Key", cli.AppKey)
	req.Header.Add("Content-Type", "application/json")
	resp, err := (&http.Client{}).Do(req)
	if err != nil {
		return 0, CancelOrderResponse{}, err
	}
	defer resp.Body.Close()

	respByte, _ := ioutil.ReadAll(resp.Body)

	var urlResp CancelOrderResponse
	json.Unmarshal(respByte, &urlResp)
	return resp.StatusCode, urlResp, nil
}

//------------------------------------

type CallbackBase struct {
	BusinessNotificationId        int    `json:"business_notification_id"  valid:"Required"`         //通知id
	NotificationType              string `json:"notification_type"  valid:"Required"`                //通知类型（ExpressOrderGot）
	BusinessNotificationCreatedAt string `json:"business_notification_created_at"  valid:"Required"` //通知创建的时间(2019-06-28 15:28:43)
}

//------------------------------------

type ExpressOrderSentCallbackData struct {
	OutBusinessOrderNumber         string `json:"out_business_order_number"  valid:"Required"`          //商家订单号(20190628072324721)
	InBusinessOrderNumber          string `json:"in_business_order_number"  valid:"Required"`           //平台订单号(19062803232469197963)
	ExpressOrderNumber             string `json:"express_order_number"  valid:"Required"`               //快递订单号(POTO1543477072416136)
	ExpressRecoveryNumber          string `json:"express_recovery_number"  valid:"Required"`            //快递取件码(null)-->用不到
	ExpressCompanyName             string `json:"express_company_name"  valid:"Required"`               //快递公司名（德邦）
	ExpressCompanyCode             string `json:"express_company_code"  valid:"Required"`               //快递公司名（DEPPON）
	ExpressOrderSuccessfullySentAt string `json:"express_order_successfully_sent_at"  valid:"Required"` //成功发送到快递公司的时间(2019-06-28 15:28:43)
}

type ExpressOrderSentCallbackResponse struct {
	CallbackBase
	Data ExpressOrderSentCallbackData `json:"data"  valid:"Required"`
}

//------------------------------------

type Couriers struct {
	CourierRealName  string `json:"courier_real_name"  valid:"Required"`  //姓名
	CourierJobNumber string `json:"courier_job_number"  valid:"Required"` //工号（顺丰没有）
	CourierPhone     string `json:"courier_phone"  valid:"Required"`      //电话
}

type ExpressOrderReceiptingCallbackData struct {
	OutBusinessOrderNumber string   `json:"out_business_order_number"  valid:"Required"` //商家订单号(20190628072324721)
	InBusinessOrderNumber  string   `json:"in_business_order_number"  valid:"Required"`  //平台订单号(19062803232469197963)
	ExpressOrderNumber     string   `json:"express_order_number"  valid:"Required"`      //快递订单号(POTO1543477072416136)
	ExpressRecoveryNumber  string   `json:"express_recovery_number"  valid:"Required"`   //快递取件码(null)-->用不到
	Couriers               Couriers `json:"couriers"  valid:"Required"`                  //快递员信息
	ReceiptingAt           string   `json:"receipting_at"  valid:"Required"`             //接货中的时间
}

type ExpressOrderReceiptingCallbackResponse struct {
	CallbackBase
	Data ExpressOrderReceiptingCallbackData `json:"data"  valid:"Required"`
}

//------------------------------------

type ExpressOrderWayBills struct {
	SurfaceNumber  string `json:"surface_number"  valid:"Required"`  //面单号（用不到~）
	TrackingNumber string `json:"tracking_number"  valid:"Required"` //运单号（5163080174）
}

type ExpressOrderGotCallbackData struct {
	OutBusinessOrderNumber string                 `json:"out_business_order_number"  valid:"Required"` //商家订单号(20190628072324721)
	InBusinessOrderNumber  string                 `json:"in_business_order_number"  valid:"Required"`  //平台订单号(19062803232469197963)
	ExpressOrderNumber     string                 `json:"express_order_number"  valid:"Required"`      //快递订单号(POTO1543477072416136)
	ExpressRecoveryNumber  string                 `json:"express_recovery_number"  valid:"Required"`   //快递取件码(null)-->用不到
	ExpressCompanyName     string                 `json:"express_company_name"  valid:"Required"`      //快递公司名（德邦）
	ExpressCompanyCode     string                 `json:"express_company_code"  valid:"Required"`      //快递公司名（DEPPON）
	WeightFromExpress      string                 `json:"weight_from_express"  valid:"Required"`       //重量(15.00)
	NumberFromExpress      int                    `json:"number_from_express"  valid:"Required"`       //数量(1)
	FreightFromExpress     int                    `json:"freight_from_express"  valid:"Required"`      //运费(616)
	WarehouseCode          string                 `json:"warehouse_code"  valid:"Required"`            //仓库code(801)
	ExpressGotAt           string                 `json:"express_got_at"  valid:"Required"`            //开单的时间(2019-06-28 15:28:43)
	ExpressOrderWaybills   []ExpressOrderWayBills `json:"express_order_waybills"  valid:"Required"`
}

type ExpressOrderGotCallbackResponse struct {
	CallbackBase
	Data ExpressOrderGotCallbackData `json:"data"  valid:"Required"`
}

//------------------------------------

type ExpressOrderSignedFromExpressCallbackData struct {
	OutBusinessOrderNumber string                 `json:"out_business_order_number"  valid:"Required"` //商家订单号(20190628072324721)
	InBusinessOrderNumber  string                 `json:"in_business_order_number"  valid:"Required"`  //平台订单号(19062803232469197963)
	ExpressOrderNumber     string                 `json:"express_order_number"  valid:"Required"`      //快递订单号(POTO1543477072416136)
	ExpressRecoveryNumber  string                 `json:"express_recovery_number"  valid:"Required"`   //快递取件码(null)-->用不到
	ExpressCompanyName     string                 `json:"express_company_name"  valid:"Required"`      //快递公司名（德邦）
	ExpressCompanyCode     string                 `json:"express_company_code"  valid:"Required"`      //快递公司名（DEPPON）
	WeightFromExpress      string                 `json:"weight_from_express"  valid:"Required"`       //重量(15.00)
	NumberFromExpress      int                    `json:"number_from_express"  valid:"Required"`       //数量(1)
	FreightFromExpress     int                    `json:"freight_from_express"  valid:"Required"`      //运费(616)
	ExpressSignedAt        string                 `json:"express_signed_at"  valid:"Required"`         //快递公司签收的时间
	ExpressOrderWaybills   []ExpressOrderWayBills `json:"express_order_waybills"  valid:"Required"`
}

type ExpressOrderSignedFromExpressCallbackResponse struct {
	CallbackBase
	Data ExpressOrderSignedFromExpressCallbackData `json:"data"  valid:"Required"`
}

//-------------------------------
type ExpressOrderCancelledCallbackData struct {
	OutBusinessOrderNumber     string                 `json:"out_business_order_number"  valid:"Required"`     //商家订单号(20190628072324721)
	InBusinessOrderNumber      string                 `json:"in_business_order_number"  valid:"Required"`      //平台订单号(19062803232469197963)
	ExpressOrderNumber         string                 `json:"express_order_number"  valid:"Required"`          //快递订单号(POTO1543477072416136)
	ExpressRecoveryNumber      string                 `json:"express_recovery_number"  valid:"Required"`       //快递取件码(null)-->用不到
	CancelledAt                string                 `json:"cancelled_at"  valid:"Required"`                  //取消时间
	CancelledReasonText        string                 `json:"cancelled_reason_text"  valid:"Required"`         //取消的原因
	CancelledReasonCode        string                 `json:"cancelled_reason_code"  valid:"Required"`         //取消原因code
	CancelledBeforeOrderStatus string                 `json:"cancelled_before_order_status"  valid:"Required"` //取消之前的状态
	ExpressOrderWaybills       []ExpressOrderWayBills `json:"express_order_waybills"  valid:"Required"`
}

type ExpressOrderCancelledCallbackResponse struct {
	CallbackBase
	Data ExpressOrderCancelledCallbackData `json:"data"  valid:"Required"`
}

//-------------------------------
type AiGuoOrderCancelledCallbackData struct {
	OutBusinessOrderNumber   string `json:"out_business_order_number"  valid:"Required"`   //商家订单号(20190628072324721)
	InBusinessOrderNumber    string `json:"in_business_order_number"  valid:"Required"`    //平台订单号(19062803232469197963)
	BusinessOrderCancelledAt string `json:"business_order_cancelled_at"  valid:"Required"` //取消时间
	CancelledReasonText      string `json:"cancelled_reason_text"  valid:"Required"`       //取消的原因
	CancelledReasonCode      string `json:"cancelled_reason_code"  valid:"Required"`       //取消原因code
}

type AiGuoOrderCancelledCallbackResponse struct {
	CallbackBase
	Data AiGuoOrderCancelledCallbackData `json:"data"  valid:"Required"`
}

//-------------------------------

// AiGuoCallback 统一回调入口
func AiGuoCallback(w http.ResponseWriter, r *http.Request) (int, interface{}, error) {
	var succeed = 1
	defer func() {
		if succeed == 0 {
			w.WriteHeader(500)
		}
	}()

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		succeed = 0
		return 0, nil, err
	}

	//把数据转到struct里
	var resp CallbackBase
	err = json.Unmarshal(body, &resp)
	if err != nil {
		succeed = 0
		return 0, nil, err
	}

	if resp.NotificationType == CONF_NOTIFY_CATEGORY[NOTIFY_CATEGORY_SENT] {
		//https: //yvj8.w.eolink.com/share/project/api/detail?groupID=-1&apiID=2759749&shareCode=LAVjtN&shareToken=$2y$10$IFxLkoRjf7xagsoFzupxNOIGBWFLZtALWOF3~2Fy981DfKJ8wotJKfa&shareID=212342
		//aiguo 给 顺丰 下单成功
		//-->此时可以拿到快递公司编码、【快递单号】、aiguo订单号、乐予的订单号

		var resp ExpressOrderSentCallbackResponse
		err = json.Unmarshal(body, &resp)
		if err != nil {
			succeed = 0
			return 0, nil, err
		}
		return NOTIFY_CATEGORY_SENT, resp, nil

	} else if resp.NotificationType == CONF_NOTIFY_CATEGORY[NOTIFY_CATEGORY_RECEIPTING] {
		//https://yvj8.w.eolink.com/share/project/api/detail?groupID=-1&apiID=2759753&shareCode=LAVjtN&shareToken=$2y$10$IFxLkoRjf7xagsoFzupxNOIGBWFLZtALWOF3~2Fy981DfKJ8wotJKfa&shareID=212342
		//分配快递员成功，开始去取件
		//-->此时可以查出【快递员的name和手机号】
		var resp ExpressOrderReceiptingCallbackResponse
		err = json.Unmarshal(body, &resp)
		if err != nil {
			succeed = 0
			return 0, nil, err
		}

		return NOTIFY_CATEGORY_RECEIPTING, resp, nil
	} else if resp.NotificationType == CONF_NOTIFY_CATEGORY[NOTIFY_CATEGORY_GOT] {
		//https://yvj8.w.eolink.com/share/project/api/detail?groupID=-1&apiID=2759752&shareCode=LAVjtN&shareToken=$2y$10$IFxLkoRjf7xagsoFzupxNOIGBWFLZtALWOF3~2Fy981DfKJ8wotJKfa&shareID=212342
		//取件成功
		//此时可以拿到【真实重量 和 数量】
		var resp ExpressOrderGotCallbackResponse
		err = json.Unmarshal(body, &resp)
		if err != nil {
			succeed = 0
			return 0, nil, err
		}

		return NOTIFY_CATEGORY_GOT, resp, nil
	} else if resp.NotificationType == CONF_NOTIFY_CATEGORY[NOTIFY_CATEGORY_SIGNEDFROMEXPRESS] {
		//https://yvj8.w.eolink.com/share/project/api/detail?groupID=-1&apiID=2759754&shareCode=LAVjtN&shareToken=$2y$10$IFxLkoRjf7xagsoFzupxNOIGBWFLZtALWOF3~2Fy981DfKJ8wotJKfa&shareID=212342
		//-->收件人签收成功
		var resp ExpressOrderSignedFromExpressCallbackResponse
		err = json.Unmarshal(body, &resp)
		if err != nil {
			succeed = 0
			return 0, nil, err
		}
		return NOTIFY_CATEGORY_SIGNEDFROMEXPRESS, resp, nil
	} else if resp.NotificationType == CONF_NOTIFY_CATEGORY[NOTIFY_CATEGORY_CANCELLED] {
		//https://yvj8.w.eolink.com/share/project/api/detail?groupID=-1&apiID=2759750&shareCode=LAVjtN&shareToken=$2y$10$IFxLkoRjf7xagsoFzupxNOIGBWFLZtALWOF3~2Fy981DfKJ8wotJKfa&shareID=212342
		//-->取消物流
		var resp ExpressOrderCancelledCallbackResponse
		err = json.Unmarshal(body, &resp)
		if err != nil {
			succeed = 0
			return 0, nil, err
		}
		return NOTIFY_CATEGORY_CANCELLED, resp, nil
	} else if resp.NotificationType == CONF_NOTIFY_CATEGORY[NOTIFY_CATEGORY_AIGUO_CANCEL] {
		//https://yvj8.w.eolink.com/share/project/api/detail?groupID=-1&apiID=2759750&shareCode=LAVjtN&shareToken=$2y$10$XQ.V9nqc6RvYCA6p9w6fxe57dObtd9qXzr8HsTG8dN~2FVy6lpMyS6e&shareID=212342
		//-->取消aiguo订单
		var resp AiGuoOrderCancelledCallbackResponse
		err = json.Unmarshal(body, &resp)
		if err != nil {
			succeed = 0
			return 0, nil, err
		}
		return NOTIFY_CATEGORY_AIGUO_CANCEL, resp, nil
	}

	//其他的都做正确处理
	//succeed = 0
	return 0, nil, nil
}

//-------------------------------
type AiGuoOrderQueryBasicData struct {
	OutBusinessOrderNumber string `json:"out_business_order_number"  valid:"Required"` //商家订单号(20190628072324721)
	InBusinessOrderNumber  string `json:"in_business_order_number"  valid:"Required"`  //平台订单号(19062803232469197963)
	BusinessOrderStatus    string `json:"business_order_status"  valid:"Required"`     //订单状态
	CancelledReasonText    string `json:"cancelled_reason_text"  valid:"Required"`     //取消的原因
	CancelledReasonCode    string `json:"cancelled_reason_code"  valid:"Required"`     //取消原因code
}

type AiGuoOrderQueryExpressData struct {
	ExpressOrderNumber string `json:"express_order_number"  valid:"Required"`
	ExpressCompanyName string `json:"express_company_name"  valid:"Required"`
	ExpressCompanyCode string `json:"express_company_code"  valid:"Required"`
	WeightFromExpress  string `json:"weight_from_express"  valid:"Required"`
}

type AiGuoOrderQueryResponse struct {
	AiGuoOrderQueryBasicData
	ExpressOrders []AiGuoOrderQueryExpressData `json:"expressOrders"  valid:"Required"`
}

//查询订单
func (cli *Client) QueryOrder(innerOrderId string) (int, AiGuoOrderQueryResponse, error) {

	reqPath := fmt.Sprintf("business/apps/%d/business-orders/%s", cli.AppID, innerOrderId)
	rawURL := cli.BaseURL + reqPath

	//计算签名
	sign := cli.genSign(reqPath, "")

	//-----------
	req, _ := http.NewRequest("GET", rawURL, nil)
	req.Header.Set("Sign", sign)
	req.Header.Set("App-Key", cli.AppKey)
	resp, err := (&http.Client{}).Do(req)
	if err != nil {
		return 0, AiGuoOrderQueryResponse{}, err
	}
	defer resp.Body.Close()

	respByte, _ := ioutil.ReadAll(resp.Body)

	if resp.StatusCode == 200 {
		var urlResp AiGuoOrderQueryResponse
		json.Unmarshal(respByte, &urlResp)
		return resp.StatusCode, urlResp, nil
	} else {
		var urlResp AiGuoOrderQueryResponse
		json.Unmarshal(respByte, &urlResp)
		errMsg := fmt.Sprintf("%+v", urlResp)
		return resp.StatusCode, AiGuoOrderQueryResponse{}, errors.New("status!=200 " + errMsg)
	}
	//---------------------

}

//-------------------------------------------
